/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.appspot.trick.it.admin.cell;

import com.appspot.trick.it.admin.TrickAdmin;
import com.appspot.trick.it.admin.api.GaeArticleAPIService;
import com.appspot.trick.it.admin.controller.EditController;
import com.appspot.trick.it.admin.controller.MainController;
import com.appspot.trick.it.admin.controller.ParameterController;
import com.appspot.trick.it.admin.custom.ArticleTreeItem;
import com.appspot.trick.it.admin.model.ArticleModel;
import com.appspot.trick.it.admin.task.ArticleDeleteTask;
import com.appspot.trick.it.admin.task.ArticleUpdateTitleTask;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.concurrent.WorkerStateEvent;
import javafx.event.ActionEvent;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SeparatorMenuItem;
import javafx.scene.control.TextField;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

/**
 *
 * @author takahara
 */
public class ArticleTreeCell extends TreeCell<ArticleModel> {

    private TextField textField;
    private final ContextMenu contextMenu = new ContextMenu();
    private final ContextMenu rootContextMenu = new ContextMenu();

    /**
     * コンストラクタ
     */
    public ArticleTreeCell() {
        
        MenuItem parameterMenuItem = new MenuItem("設定");
        
        MenuItem addFolderMenuItem = new MenuItem("記事の追加");
        MenuItem changeNameMenuItem = new MenuItem("記事名の変更");
        MenuItem deleteFolderMenuItem = new MenuItem("削除");
        MenuItem refreshmentMenuItem = new MenuItem("更新");
        MenuItem editMenuItem = new MenuItem("編集");
        MenuItem publicMenuItem = new MenuItem("公開/非公開");
        MenuItem changeIndexUpperMenuItem = new MenuItem("上へ ↑");
        MenuItem changeIndexLowerMenuItem = new MenuItem("下へ ↓");
        
        addFolderMenuItem.setGraphic(getMenuItemIcon("images/context_menu/add.png"));
        refreshmentMenuItem.setGraphic(getMenuItemIcon("images/context_menu/refresh.png"));
        deleteFolderMenuItem.setGraphic(getMenuItemIcon("images/context_menu/delete.png"));
        editMenuItem.setGraphic(getMenuItemIcon("images/context_menu/edit.png"));
        changeNameMenuItem.setGraphic(getMenuItemIcon("images/context_menu/edit.png"));
        
        rootContextMenu.getItems().addAll(refreshmentMenuItem, new SeparatorMenuItem(), addFolderMenuItem, new SeparatorMenuItem(), parameterMenuItem);
        contextMenu.getItems().addAll(
                refreshmentMenuItem, 
                new SeparatorMenuItem(), 
                editMenuItem, 
                changeNameMenuItem, 
                publicMenuItem, 
                new SeparatorMenuItem(), 
                addFolderMenuItem, 
                new SeparatorMenuItem(), 
                changeIndexUpperMenuItem,
                changeIndexLowerMenuItem,
                new SeparatorMenuItem(), 
                deleteFolderMenuItem);


        // 記事追加メニューイベント
        addFolderMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                try {
                    
                    MainController.getInstance().getArticleAddTask().setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                        @Override
                        public void handle(WorkerStateEvent t) {

                            ArticleModel model = (ArticleModel) t.getSource().getValue();
                            // フォルダが開いてない場合はOPENする
                            if (!getTreeItem().expandedProperty().get()) {
                                getTreeItem().setExpanded(true);
                            }

                            // TreeViewにフォルダを追加
                            ArticleTreeItem newTreeItem = new ArticleTreeItem(model);
                            getTreeItem().getChildren().add(newTreeItem);
                        }
                    });
                    
                    MainController.getInstance().getArticleAddTask().setOnFailed(new EventHandler<WorkerStateEvent>() {
                        @Override
                        public void handle(WorkerStateEvent t) {

                            MainController.getInstance().getArticleAddTask().getException().printStackTrace();
                        }
                    });
                    
                    MainController.getInstance().getArticleAddTask().run(getTreeItem().getValue());
                    
                } catch (Exception ex) {
                    Logger.getLogger(ArticleTreeCell.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });


        // 名前変更メニューイベント
        changeNameMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                // treeView を変更可能に設定し、変更開始する
                getTreeView().editableProperty().set(true);
                startEdit();
            }
        });


        // 削除メニューイベント
        deleteFolderMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                ArticleDeleteTask task = MainController.getInstance().getArticleDeleteTask();
                task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                    @Override
                    public void handle(WorkerStateEvent t) {
                        getTreeItem().getParent().getChildren().remove(getTreeItem());
                    }
                });
                
                task.run(getItem());
            }
        });
        
        
        // 更新メニューイベント
        refreshmentMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                MainController.getInstance().getArticleLoadListTask().setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                    @Override
                    public void handle(WorkerStateEvent t) {

                        List<ArticleTreeItem> folderList = (List<ArticleTreeItem>) t.getSource().getValue();
                        getTreeItem().getChildren().setAll(folderList);
                        
                        MainController.getInstance().getArticleTreeView().getSelectionModel().select(getTreeItem());
                    }
                });

                MainController.getInstance().getArticleLoadListTask().run(getItem().getKey());
            }
        });
        
        
        // 編集メニューイベント
        editMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                EditController editController = new EditController(getItem());
                TrickAdmin.getInstance().showArticleStage(editController, getItem().getTitle());
            }
        });
        
        // 公開/非公開メニュー
        publicMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                try {
                    final GaeArticleAPIService service = new GaeArticleAPIService(MainController.getInstance().getSiteMstEntity());
                    ArticleModel model = getItem();
                    model.setPublicFlg(!model.isPublicFlg());
                    service.changePublicFlg(model.getKey());
                    
                    if (model.isPublicFlg()) {
                        ImageView iconImage = new ImageView(TrickAdmin.class.getResource("images/etc/public.png").toString());
                        iconImage.setFitHeight(15.0);
                        iconImage.setPreserveRatio(true);
                        setGraphic(iconImage);
                    } else {
                        ImageView iconImage = new ImageView(TrickAdmin.class.getResource("images/etc/private.png").toString());
                        iconImage.setFitHeight(15.0);
                        iconImage.setPreserveRatio(true);
                        setGraphic(iconImage);
                    }
                    
                } catch (Exception ex) {
                    Logger.getLogger(ArticleTreeCell.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        
        // ---------------------------------------------------------------------
        // 上移動イベント
        // ---------------------------------------------------------------------
        changeIndexUpperMenuItem.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                TreeItem<ArticleModel> sel = getTreeItem();
                if (sel != null) {
                    List<ArticleModel> keysList = new ArrayList();
                    TreeItem<ArticleModel> prarent = sel.getParent();
                    

                    if (prarent != null) {
                        
                        int nIndex = prarent.getChildren().indexOf(sel);
                        if (nIndex > 0) {
                            try {
                                prarent.getChildren().removeAll(sel);
                                prarent.getChildren().add(nIndex - 1, sel);
                                
                                for (TreeItem<ArticleModel> treeItem : prarent.getChildren()) {
                                    keysList.add(treeItem.getValue());
                                }

                                MainController.getInstance().getArticleChangeIndexTask().run(keysList);
                                
                            } catch (Exception ex) {
                                Logger.getLogger(ArticleTreeCell.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        });
        
        
        // ---------------------------------------------------------------------
        // 下移動イベント
        // ---------------------------------------------------------------------
        changeIndexLowerMenuItem.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent t) {
                TreeItem<ArticleModel> sel = getTreeItem();
                if (sel != null) {
                    List<ArticleModel> keysList = new ArrayList();
                    TreeItem<ArticleModel> prarent = sel.getParent();

                    if (prarent != null) {
                        int nIndex = prarent.getChildren().indexOf(sel);
                        if (nIndex < prarent.getChildren().size() - 1) {
                            try {
                                prarent.getChildren().removeAll(sel);
                                prarent.getChildren().add(nIndex + 1, sel);

                                for (TreeItem<ArticleModel> treeItem : prarent.getChildren()) {
                                    keysList.add(treeItem.getValue());
                                }

                                MainController.getInstance().getArticleChangeIndexTask().run(keysList);
                                
                            } catch (Exception ex) {
                                Logger.getLogger(ArticleTreeCell.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }
                    }
                }
            }
        });
        
        // サイト設定メニューイベント
        parameterMenuItem.setOnAction(new EventHandler() {
            @Override
            public void handle(Event t) {
                ParameterController controller = new ParameterController();
                TrickAdmin.getInstance().showParameterStage(controller);
            }
        });
    }

    @Override
    public void startEdit() {
        super.startEdit();

        if (textField == null) {
            createTextField();
        }
        setText(null);
        setGraphic(textField);
        textField.selectAll();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setText(getItem().getTitle());
        setGraphic(getTreeItem().getGraphic());

        // treeView を変更不可に設定する
        getTreeView().editableProperty().set(false);
    }

    @Override
    public void commitEdit(ArticleModel articleModel) {
        try {
            super.commitEdit(articleModel);
            
            ArticleUpdateTitleTask task = MainController.getInstance().getArticleUpdateTitleTask();
            task.run(articleModel);

            // treeView を変更不可に設定する
            getTreeView().editableProperty().set(false);

        } catch (Exception ex) {
            Logger.getLogger(ArticleTreeCell.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * セル更新
     *
     * @param item
     * @param empty
     */
    @Override
    public void updateItem(final ArticleModel item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            super.setText(item.getTitle());

            if (!getTreeItem().isLeaf() && getTreeItem().getParent() != null) {
                setContextMenu(contextMenu);
                
            }else {
                setContextMenu(rootContextMenu);
            }
            
            // 公開フラグ
            if (getItem().getKey() != null) {
                if (getItem().isPublicFlg()) {
                    ImageView iconImage = new ImageView(TrickAdmin.class.getResource("images/etc/public.png").toString());
                    iconImage.setFitHeight(15.0);
                    iconImage.setPreserveRatio(true);
                    setGraphic(iconImage);
                } else {
                    ImageView iconImage = new ImageView(TrickAdmin.class.getResource("images/etc/private.png").toString());
                    iconImage.setFitHeight(15.0);
                    iconImage.setPreserveRatio(true);
                    setGraphic(iconImage);
                }
            }

        }
    }

    private void createTextField() {
        final ArticleModel model = getItem();
        textField = new TextField(model.getTitle());
        textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
            @Override
            public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ENTER) {
                    model.setTitle(textField.getText());
                    commitEdit(model);
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            }
        });
    }
    
    
    /**
     * メニューアイコンの取得
     * @param path
     * @return 
     */
    private ImageView getMenuItemIcon(String path) {
        ImageView menuItemIcon = new ImageView(TrickAdmin.class.getResource(path).toString());
        menuItemIcon.setFitHeight(17);
        menuItemIcon.setPreserveRatio(true);
        
        return menuItemIcon;
    }
}
